/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package RuleInterence;

import Common.Constant;
import DataSource.Data;
import DataSource.DataEntry;
import DataSource.Subscriber;
import Logger.ILog;
import Logger.LogManager;
import java.util.Vector;

/**
 *
 * @author Tuan
 */
public class RuleCheckerImpl implements Subscriber, RuleChecker{

    private Vector rules;
    
    private static ILog logger = LogManager.GetLogger(RuleCheckerImpl.class.getName());
    
    private Vector listeners;
    
    public RuleCheckerImpl(DataEntry entry){
        this.listeners = new Vector();
        Rule healthyRule = new HealthyRule(entry);        
        
        DataEntry hypotensionEntry = new DataEntry();       
        hypotensionEntry.setMinSBP(Constant.HYPOTENSION_MIN_SBP);
        hypotensionEntry.setMaxSBP(Constant.HYPOTENSION_MAX_SBP);
        hypotensionEntry.setMinDBP(Constant.HYPOTENSION_MIN_DBP);
        hypotensionEntry.setMaxDBP(Constant.HYPOTENSION_MAX_DBP);
        Rule hypotensionRule = new Hypotension(hypotensionEntry);
        
        DataEntry stage1Entry = new DataEntry();    
        stage1Entry.setMinSBP(Constant.HYPERTENSION_MIN_SBP_STAGE1);
        stage1Entry.setMaxSBP(Constant.HYPERTENSION_MAX_SBP_STAGE1);
        stage1Entry.setMinDBP(Constant.HYPERTENSION_MIN_DBP_STAGE1);
        stage1Entry.setMaxDBP(Constant.HYPERTENSION_MAX_DBP_STAGE1);
        Rule hyperStage1Rule = new HypertensionStage1Rule(stage1Entry);
        
        
        DataEntry stage2Entry = new DataEntry();    
        stage2Entry.setMinSBP(Constant.HYPERTENSION_MIN_SBP_STAGE2);
        stage2Entry.setMaxSBP(Constant.HYPERTENSION_MAX_SBP_STAGE2);
        stage2Entry.setMinDBP(Constant.HYPERTENSION_MIN_DBP_STAGE2);
        stage2Entry.setMaxDBP(Constant.HYPERTENSION_MAX_DBP_STAGE2);
        Rule hyperStage2Rule = new HypertensionStage2Rule(stage2Entry);
        
        DataEntry stage3Entry = new DataEntry();    
        stage3Entry.setMinSBP(Constant.HYPERTENSION_MIN_SBP_STAGE3);
        stage3Entry.setMaxSBP(Constant.HYPERTENSION_MAX_SBP_STAGE3);
        stage3Entry.setMinDBP(Constant.HYPERTENSION_MIN_DBP_STAGE3);
        stage3Entry.setMaxDBP(Constant.HYPERTENSION_MAX_DBP_STAGE3);
        Rule hyperStage3Rule = new HypertensionStage3Rule(stage3Entry);
        
        DataEntry heartStrokeEntry = new DataEntry();    
        heartStrokeEntry.setMinHeartBeat(entry.getMinHeartBeat());
        heartStrokeEntry.setMaxHeartBeat(entry.getMaxHeartBeat());        
        Rule heartStrokeRule = new HeartStrokeRule(heartStrokeEntry, hypotensionRule, healthyRule);
        
        rules = new Vector();
        if(entry.isIsHeathy()){
            rules.addElement(healthyRule);
        }
        if(entry.isIsHeartStroke()){
            rules.addElement(heartStrokeRule);
        }
        if(entry.isIsHypotension()){
            rules.addElement(hypotensionRule);
        }
        if(entry.isIsHypertensionStage1()){
            rules.addElement(hyperStage1Rule);
        }
        if(entry.isIsHypertensionStage2()) {
            rules.addElement(hyperStage2Rule);
        }
        if(entry.isIsHypertensionStage3()) {
            rules.addElement(hyperStage3Rule);
        }        
    }    
      
    public synchronized void update(Data data) {
        StringBuffer builder = new StringBuffer();
        for(int i = 0; i < this.rules.size(); i++){
            Rule rule = (Rule)this.rules.elementAt(i);
            DiagnosticResult result = rule.checkSymptom(data);
            if(result != null){
                builder.append(result.getSymptom()).append(" ");
            }
        }
        
        //logger.info();
        if(builder.length() == 0){
            logger.info(data.toString() + " Cannot determine");
            onComplete("", data);
        } else {
            onComplete(builder.toString(), data);
        }
    }
    
    private void onComplete(String result, Data data){
        for(int i = 0; i < this.listeners.size(); i++){
            RuleCheckerListener listener = (RuleCheckerListener)this.listeners.elementAt(i);
            listener.onComplete(result, data);
        }
    }

    public synchronized void registerCallback(RuleCheckerListener listener) {
        this.listeners.addElement(listener);
    }
}
